import time
from PIL import Image
from selenium import webdriver
from chaojiying import Chaojiying_Client
from selenium.webdriver import ActionChains


# 大体的流程
# 1. 使用selenium打开12306登录的URL
# 2. 使用xpath定位到 用户名、密码
# 3. 等待选择验证码（第一版 采用 人为选择的方式，第二版再采用自动选择的方式）
# 4. 使用xpath定位到 立即登录
# 5. 点击 立即登录

class TrainSpider(object):
    
    def __init__(self):
        # 使用selenium打开谷歌浏览器
        self.driver = webdriver.Chrome()
    
        # 设置窗口的大小
        # driver.set_window_size(1200, 1000)
        self.driver.maximize_window()  # 最大化窗口
    
    @staticmethod
    def click_locxy(dr, x, y, left_click=True):
        """
        dr:浏览器
        x:页面x坐标
        y:页面y坐标
        left_click:True为鼠标左键点击，否则为右键点击
        """
        if left_click:
            ActionChains(dr).move_by_offset(x, y).click().perform()
        else:
            ActionChains(dr).move_by_offset(x, y).context_click().perform()
        ActionChains(dr).move_by_offset(-x, -y).perform()  # 将鼠标位置恢复到移动前
        
    def get_url(self):
        # 打开一个带有普通验证码的登录页面
        self.driver.get("https://kyfw.12306.cn/otn/resources/login.html")
        time.sleep(2)
    
    def click_account_login(self):
        # 定位到"账号登录"，然后点击
        self.driver.find_element_by_xpath("//li[@class='login-hd-account']").click()
        time.sleep(1)
        
    def input_user_name(self):
        # 输入用户名
        self.driver.find_element_by_xpath("//input[@id='J-userName']").send_keys("dong4716138")
        # 输入密码
        self.driver.find_element_by_xpath("//input[@id='J-password']").send_keys("xxxx")
    
    @staticmethod
    def click_captcha_by_self():
        input("请先手动点击验证码，然后按下回车...")
        
    def click_captcha_auto(self):
        # 1. 截屏
        # 2. 从上一步的图片中截取出验证码
        # 3. 将验证码传递到打码平台
        # 4. 将上一步返回的x,y转换为 鼠标在当前页面中 要点击的x,y
        # 5. 模拟点击
    
        # 截屏
        self.driver.get_screenshot_as_file('12306_screenshot.png')
        print(">>>1:已经截屏")
    
        # 提取验证码位置
        img_element = self.driver.find_element_by_xpath("//img[@id='J-loginImg']")
        # 注意，因为本代码是在Mac电脑下运行因为Mac电脑的像素是普通电脑的2倍，所以下面在定位位置时要乘以2倍
        left = int(img_element.location['x']) * 2
        top = int(img_element.location['y']) * 2
        right = int(img_element.location['x'] + img_element.size['width']) * 2
        bottom = int(img_element.location['y'] + img_element.size['height']) * 2
        # 通过Image处理图像
        im = Image.open('12306_screenshot.png')
        im = im.crop((left, top, right, bottom))
        # 保存得到的验证码图片
        im.save('12306_code.png')
        print(">>>2:提取验证码完成")
    
        # 因为Mac的像素是普通电脑的2倍，所以上面的代码乘以2，所以下面的代码是将图片缩小到原来的大小，否则超级鹰识别出来的位置不准确
        # 下面压缩的代码，Mac电脑使用，非Mac或者Mac不是retina屏幕 也无需考虑
        # 压缩图片
        width = im.size[0]  # 获取宽度
        height = im.size[1]  # 获取高度
        img = im.resize((int(width * 0.5), int(height * 0.5)), Image.ANTIALIAS)
        img.save("12306_code_2.png")
        print(">>>3:缩小图片已完成")
    
        # 上传到打码平台
        chaojiying = Chaojiying_Client('dong4716138', 'wangmingdong123', '900505')  # 用户中心>>软件ID 生成一个替换 96001
        im = open('12306_code_2.png', 'rb').read()  # 本地图片文件路径 来替换 a.jpg 有时WIN系统须要//
        ret = chaojiying.PostPic(im, 9004)  # 1902 验证码类型  官方网站>>价格体系 3.4+版 print 后要加()
    
        captcha_positions = ret['pic_str']
    
        print(">>>5:超级鹰已经识别出验证码坐标")
        print("验证码位置是：", captcha_positions)
    
        # 模拟点击图片验证码
        for one_position in captcha_positions.split("|"):  # "50,72|32,152"---->  ['50,72', '32,152']
            x, y = one_position.split(",")  # ["50", "72"], 此时x="50"  y="72"
            self.click_locxy(self.driver, int(left / 2) + int(x), int(top / 2) + int(y))  # 左键点击
            time.sleep(0.5)
    
        print(">>>6:模拟点击已完成...")
    
    def run(self):
        # 打开一个带有普通验证码的登录页面
        self.get_url()
        
        # 定位到"账号登录"，然后点击
        self.click_account_login()
        
        # 输入用户名、密码
        self.input_user_name()
        
        # 选择图片验证码的方式
        op = input("输入1表示：手动点击验证码\n输入2表示：自动点击验证码")
        
        if op == "1":
            # 手动验证码
            self.click_captcha_by_self()
        elif op == "2":
            # 自动验证的流程
            self.click_captcha_auto()
        
        input("输入任意内容，按下回车 开始登录...")
        time.sleep(2)
        
        # 点击登录
        self.driver.find_element_by_xpath("//a[@id='J-login']").click()

        input("输入任意内容，按下回车，程序over....")
        
        # 退出谷歌浏览器
        self.driver.quit()


if __name__ == '__main__':
    # 创建爬虫对象
    spider_12306 = TrainSpider()
    # 调用其run方法开始爬取
    spider_12306.run()
